package cn.song.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.song.entity.excel.ExcelDataModel;
import cn.song.entity.hutool.ExcelModel;
import cn.song.model.DownloadDto;
import cn.song.util.easyexcel.DownloadUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Hutool服务实现
 *
 * @author SongRenShuo
 * @date 2025/01/06
 */
@Slf4j
@Service("hutoolExcelService")
public class HutoolExcelService implements ExcelService {

    @Autowired
    private DownloadUtil downloadUtil;

    @Autowired
    private TaskExecutor asyncExecutor;

    @Override
    public List<ExcelDataModel> uploadExcel(MultipartFile file) throws IOException {
        try (InputStream inputStream = file.getInputStream()) {
            // 使用Hutool的Excel读取器
            ExcelReader reader = ExcelUtil.getReader(inputStream);
            // 读取Excel数据，跳过标题行
            List<ExcelModel> excelModels = reader.readAll(ExcelModel.class);

            log.info("Hutool读取Excel成功，共读取{}条数据", excelModels.size());

            // 转换为统一数据模型
            return excelModels.stream()
                    .map(this::convertToExcelDataModel)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("Hutool读取Excel文件失败", e);
            throw new IOException("读取Excel文件失败: " + e.getMessage());
        }
    }

    @Override
    public void downloadExcel(List<ExcelDataModel> dataList, HttpServletResponse response, String fileName) throws IOException {
        // 转换为Hutool模型
        List<ExcelModel> excelModels = dataList.stream()
                .map(this::convertToExcelModel)
                .collect(Collectors.toList());

        // 通过工具类创建writer
        ExcelWriter writer = cn.hutool.poi.excel.ExcelUtil.getWriter();

        // 自定义标题别名
        writer.addHeaderAlias("id", "序号");
        writer.addHeaderAlias("name", "姓名");
        writer.addHeaderAlias("birthday", "生日");
        writer.addHeaderAlias("age", "年龄");

        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(excelModels, true);

        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

        ServletOutputStream out = response.getOutputStream();
        writer.flush(out, true);
        writer.close();
        IoUtil.close(out);
    }

    @Override
    public void downloadTemplate(HttpServletResponse response, String fileName) throws IOException {
        // 生成示例数据
        List<ExcelModel> templateData = generateTemplateData();

        // 通过工具类创建writer
        ExcelWriter writer = cn.hutool.poi.excel.ExcelUtil.getWriter();

        // 自定义标题别名
        writer.addHeaderAlias("id", "序号");
        writer.addHeaderAlias("name", "姓名");
        writer.addHeaderAlias("birthday", "生日");
        writer.addHeaderAlias("age", "年龄");

        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(templateData, true);

        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

        ServletOutputStream out = response.getOutputStream();
        writer.flush(out, true);
        writer.close();
        IoUtil.close(out);
    }

    @Override
    public String processExcelAsync(MultipartFile file, DownloadDto downloadDto) {
        String taskId = IdUtil.fastSimpleUUID();

        // 异步处理
        asyncExecutor.execute(() -> {
            try {
                List<ExcelDataModel> dataList = uploadExcel(file);
                log.info("Hutool异步处理完成，共处理{}条数据", dataList.size());

                // 更新任务状态
                downloadDto.setDescription("处理完成，共处理" + dataList.size() + "条数据");
                downloadUtil.updateDownloadList(downloadDto);

            } catch (Exception e) {
                log.error("Hutool异步处理失败", e);
                downloadDto.setDescription("处理失败：" + e.getMessage());
                downloadUtil.updateDownloadList(downloadDto);
            }
        });

        return taskId;
    }

    @Override
    public String getServiceType() {
        return "hutool";
    }

    /**
     * 转换为统一数据模型
     */
    private ExcelDataModel convertToExcelDataModel(ExcelModel excelModel) {
        return ExcelDataModel.builder()
                .id(excelModel.getId())
                .name(excelModel.getName())
                .birthday(excelModel.getBirthday())
                .age(excelModel.getAge())
                .createTime(new Date())
                .updateTime(new Date())
                .build();
    }

    /**
     * 转换为Hutool模型
     */
    private ExcelModel convertToExcelModel(ExcelDataModel dataModel) {
        return ExcelModel.builder()
                .id(dataModel.getId())
                .name(dataModel.getName())
                .birthday(dataModel.getBirthday())
                .age(dataModel.getAge())
                .build();
    }

    /**
     * 生成模板数据
     */
    private List<ExcelModel> generateTemplateData() {
        List<ExcelModel> templateData = new ArrayList<>();

        templateData.add(ExcelModel.builder()
                .id("示例ID001")
                .name("张三")
                .birthday(DateUtil.date())
                .age(25)
                .build());

        templateData.add(ExcelModel.builder()
                .id("示例ID002")
                .name("李四")
                .birthday(DateUtil.yesterday())
                .age(30)
                .build());

        return templateData;
    }
}
